﻿#include "ProtocolBase.h"
#include <stdlib.h>
#include <string.h>
#include <thread>
#include <chrono>
#include "../Logic/logic.h"
#include "../Publicfunc/publicFunc.h"

void protocol::TprotocolBaseClass::resetRecvRequest()
{
    _recvDataTag.headReady = false;
}

void protocol::TprotocolBaseClass::resetSendRequest()
{
    _sendDataTag.headReady = false;
}

void protocol::TprotocolBaseClass::readThread()
{
    uint8_t lvRecvBuffer[4096];
    int8_t  lvReadedLen;
    while (true)
    {
        lvReadedLen = readData(lvRecvBuffer, sizeof(lvRecvBuffer));
        if (lvReadedLen <= 0)
        {
            break;
        }
        else
        {
            processRecvData(lvRecvBuffer, lvReadedLen);
        }
    }
    setClose();
}

void protocol::TprotocolBaseClass::writeThread()
{
    EPopStates lvHasSendData;

    uint8_t lvTimeOutTimes = 0;
    while (true)
    {
		if (isClosed())
		{
            goto tagBreakAll;
		}
        lvHasSendData = _sendDatas.pop(_sendData, _timeOutSec);
        if (lvHasSendData == EPopStates::timeout)
        {
            lvTimeOutTimes++;
            //超时逻辑
            SC::log("超时", lvTimeOutTimes);
            continue;
        }
        lvTimeOutTimes = 0;
        if (lvHasSendData == EPopStates::succ && !processSendData())
        {
            goto tagBreakAll;
        }           
    }  

tagBreakAll:
    setClose();
}

uint32_t protocol::TprotocolBaseClass::readHead(uint8_t *avBuf, uint32_t avLength)
{
    return readData(avBuf, avLength, _recvData.headData);
}

uint32_t protocol::TprotocolBaseClass::readExtend(uint8_t *avBuf, uint32_t avLength)
{
    uint32_t readed = readData(avBuf, avLength, _recvData.extendHeadData);
    return readed;
}

uint32_t protocol::TprotocolBaseClass::readUserData(uint8_t *avBuf, uint32_t avLength)
{
    return readData(avBuf, avLength, _recvData.payload);
}

uint32_t protocol::TprotocolBaseClass::readData(uint8_t *avBuf, uint32_t avLength, std::vector<uint8_t>& avData)
{
    uint32_t lvNeedLen = avData.capacity() - avData.size();
    if (lvNeedLen > avLength )
    {
        avData.insert(avData.begin(), avBuf, avBuf + avLength);
        return 0;
    }
    else
    {
        avData.insert(avData.begin(), avBuf, avBuf + lvNeedLen);
    }
    return lvNeedLen;
}

bool protocol::TprotocolBaseClass::sendData(std::vector<uint8_t>& avData, int32_t& avErrCode)
{
    avErrCode = 0;
    uint32_t lvSended = writeData(avData.data(), avData.size());
    if (lvSended > 0)
    {
        avData.erase(avData.begin(), avData.begin() + lvSended);
    }
    else
    {
        avErrCode = GetLastError();
    }
    return avData.empty();
}

void protocol::TprotocolBaseClass::setClose()
{
    std::lock_guard<std::mutex> lvLock(_locker);
    if (!_closed)
    {
		this->disConnect();
		_closed = true;
    }
    
    _sendDatas.closeQueue();
    _recvDatas.closeQueue();
}

bool protocol::TprotocolBaseClass::isClosed()
{
    std::lock_guard<std::mutex> lvLock(_locker);
    return _closed;
}

void protocol::TprotocolBaseClass::setTerminate(bool avTerminate)
{
	std::lock_guard<std::mutex> lvLock(_locker);
    _terminate = avTerminate;
}

bool protocol::TprotocolBaseClass::isTerminate()
{
	std::lock_guard<std::mutex> lvLock(_locker);
	return _terminate;
}

void protocol::TprotocolBaseClass::startService()
{
    while (true)
    {
        if (connectToServer() == 0)
        {   
            TlogicManage::sendOnlineData(this);
            std::thread lvReadThread(&protocol::TprotocolBaseClass::readThread, this);      //接收数据，放进接收队列
            std::thread lvWriteThread(&protocol::TprotocolBaseClass::writeThread, this);    //从发送队列取出数据发送

            //处理接收到的数据
            TmetaData lvMetaData;
            EPopStates lvPopSucc;
            while (true)
            {
                if (isClosed())
                {
                    break;
                }
                lvPopSucc = _recvDatas.pop(lvMetaData, 0);
                if (lvPopSucc != EPopStates::succ)
                {
                    break;
                }

                TlogicManage::processRecvPackge(this, &lvMetaData);
            }

            lvReadThread.join();
            lvWriteThread.join();

            _sendDatas.clear();
            _recvDatas.clear();

            if (this->isTerminate())
            {
                break;
            }
        }
        else
        {
            std::this_thread::sleep_for(std::chrono::seconds(2));
        }
    }
}

uint32_t protocol::TprotocolBaseClass::putSendData(TmetaData&& avData)
{
    _sendDatas.push(std::move(avData));
    return 0;
}

bool protocol::TprotocolBaseClass::processRecvData(uint8_t *avBuf, uint32_t avLength)
{
    if (avLength == 0)
    {
        return true;
    }

    TprotocolHead lvHead;
    uint32_t offset = 0;
    if  (!_recvDataTag.headReady)  //如果头还没准备好，接收头
    {
        offset = readHead(avBuf, avLength);
        if (offset == 0)
        {
            return true;
        }
        avBuf += offset;
        avLength -= offset;

        _recvDataTag.headReady = true;
        lvHead = *((TprotocolHead*)_recvData.headData.data());
//判断是否要读扩展数据 extendReady为true时，说明扩展头已经读完了(或没有扩展头)
        _recvDataTag.extendReady = true;
        if  (lvHead.extendHead > 0)
        {   //有扩展头，初始化接收扩展头的几个变量。
            _recvData.extendHeadData.reserve(lvHead.extendHead);
            _recvDataTag.extendReady = false;
        }
        //初始化接收数据的几个变量
        _recvDataTag.dataReady = true;
        if  (lvHead.dataLen > 0)
        {
            _recvDataTag.dataReady = false;
            _recvData.payload.reserve(lvHead.dataLen);
        }
    }

    if  (_recvDataTag.headReady)
    {
        lvHead = *((TprotocolHead*)_recvData.headData.data());

        if (!_recvDataTag.extendReady)  //如果头接收完了，但扩展头还没有接收完，接收扩展头
        {
            offset = readExtend(avBuf, avLength);
            if (offset == 0)
            {
                return true;
            }
            avBuf += offset;
            avLength -= offset;
            _recvDataTag.extendReady = true;
        }

        if (_recvDataTag.extendReady)   //如果扩展头接收完了，接收用户数据
        {
            if  (!_recvDataTag.dataReady)
            {
                offset = readUserData(avBuf, avLength);
                if (offset == 0)
                {
                    return true;
                }
                avBuf += offset;
                avLength -= offset;
            }      
            _recvDataTag.dataReady = true;
        }

        _recvDatas.push(std::move(_recvData));  //所有数据收完后，放入接收队列

		resetRecvRequest();
		return processRecvData(avBuf, avLength);
    }
    return true;
}

bool protocol::TprotocolBaseClass::processSendData()
{
    int32_t lvErrCode;
    bool lvResult = true;
    if  (!_sendDataTag.headReady) //发送头
    {
        _sendDataTag.headReady = sendData(_sendData.headData, lvErrCode);
        if (_sendDataTag.headReady)
        {
            _sendDataTag.extendReady = true;
            if (!_sendData.extendHeadData.empty())
            {
                _sendDataTag.extendReady = false;
            }
            _sendDataTag.dataReady = true;
			if (!_sendData.payload.empty())
			{
				_sendDataTag.dataReady = false;
			}
        }
        else {
            lvResult = lvErrCode == 0;
        }
    }

    if  (_sendDataTag.headReady)
    {
        if  (!_sendDataTag.extendReady) //发送扩展头
        {
            _sendDataTag.extendReady = sendData(_sendData.extendHeadData, lvErrCode);
            if (!_sendDataTag.extendReady)
            {
                lvResult = lvErrCode == 0;
            }
        }

        if  (_sendDataTag.extendReady && !_sendDataTag.dataReady)
        {
            _sendDataTag.dataReady = sendData(_sendData.payload, lvErrCode);
            if  (!_sendDataTag.dataReady)
            {
                lvResult = lvErrCode == 0;
            }
        }
        resetSendRequest();
    }
    return lvResult;
}
